#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This application is released under the GNU General Public License
# v3 (or, at your option, any later version). You can find the full
# text of the license under http://www.gnu.org/licenses/gpl.txt.
# By using, editing and/or distributing this software you agree to
# the terms and conditions of this license.
# Thank you for using free software!

#  PastebinScreenlet (c) Alsor Zhou 2009 <alsor DOT zhou {AT} gmail DOT com>

import screenlets
from screenlets import DefaultMenuItem
from screenlets.options import ColorOption, StringOption, FloatOption

import cairo
import rsvg
import gtk
import os
import pango
import subprocess
import gobject
import re
import urllib
import fileinput

import Config
import HTMLResponseParser

class PastebinScreenlet (screenlets.Screenlet):
	"""A Screenlet to monitor the current Dropbox synchronisation status."""
	__name__	= 'PastebinScreenlet'
	__version__ = '0.1'
	__author__	= 'Alsor Zhou'
	__desc__	= __doc__

	__data__ = None					# the current clipboard data
	__clipboard_type__ = True		# default drag clipboard text/img

	# pastebin http request param related variables
	_user_ = ""						# user in pastebin service
	_remember_me_ = False			# remember user for later editing
	_expire_duration_ = "f";		# f = forever; m = month; d = day
	expire_duration_options = ["Day", "Month", "Forever"];

	update_interval = 1
	mouse_is_hover = False
	mouse_press = False
	dragging = False

	__config__ = None;

	# select pastebin service from options
	service_default_name = "Pastebin"
	service_name = ""
	service_default_url = "http://pastebin.com/"
	service_url = ""
	services_options = None;

	# editable options
	background_colour = (0,0,0, 0.2)
	bar_out_colour = (0.68,0.81,0.94, 0.8)
	bar_back_colour = (0.96,0.98,1, 0.8)
	bar_fill_colour = (0.2,0.55,0.83, 0.8)

	def __init__ (self, **keyword_args):
		screenlets.Screenlet.__init__(self,
			width=300, height=300, uses_theme=True,
			drag_drop=True, **keyword_args)
		self.update_interval = self.update_interval
		self.__timeout = gobject.timeout_add(1000, self.update)

		# init clipboard
		self.clipboard	= gtk.Clipboard(selection="PRIMARY")
		self.clipboard.connect('owner-change', self.clipboard_owner_change)

		# Set the default theme
		self.theme_name = "default"

		# Add user-editable settings
		self.add_options_group('Pastebin',
			'Configure Pastebin Screenlet.')

		self.add_option(StringOption('Pastebin', '_user_',
			self._user_,'Username', 'User in pastebin service'));

		self.add_option(BoolOption('Pastebin', '_remember_me_',
			self._remember_me_,'Remember me', 'Remember user for later editing'));

		self.add_option(BoolOption('Pastebin', '_expire_duration_',
			self._expire_duration_,'Remember me', 'Remember user for later editing'));

		# Dynamic generate options from config file
		self.__config__ = Config();
		try:
			self.__config__.config_open("Config.ini");
			for s in self.__config__.parse_service_list():
				self.services_options.append(s[0]);

			self.add_option(StringOption('Pastebin', 'service',
				self.service,'Pastebin service provider',
				'', choices = self.services_options));
		except:
			self.config_open_fault_handler();

		# Appearance options group
		self.add_options_group('Appearance',
			'Configure screenlet appearance.')
		# Background colour
		self.add_option(ColorOption('Appearance','background_colour',
			self.background_colour, 'Back colour', 'background_colour'))
		# Bar outline colour
		self.add_option(ColorOption('Appearance','bar_out_colour',
			self.bar_out_colour, 'Bar outline colour', 'bar_out_colour'))
		# Bar background colour
		self.add_option(ColorOption('Appearance','bar_back_colour',
			self.bar_back_colour, 'Bar background colour', 'bar_back_colour'))
		# Bar fill colour
		self.add_option(ColorOption('Appearance','bar_fill_colour',
			self.bar_fill_colour, 'Bar fill colour', 'bar_fill_colour'))

	def config_open_fault_handler(self):
		self.service_name = self.service_default_name;
		self.service_url = self.service_default_url;

	def on_init (self):
		print ("Screenlet has been initialized.")
		# add default menuitems
		self.add_default_menuitems()
		self.clipboard_owner_change (self.clipboard, None)

	def clipboard_owner_change (self, clipboard, event):
		'''New data in the clipboard'''
		self.__data__ = None
		self.__clipboard_type__ = True

		# get the data
		if clipboard.wait_is_text_available():
			#print ("Clipboard is text type")
			self.__data__ = clipboard.wait_for_text()
		elif clipboard.wait_is_image_available():
			#print ("Clipboard is img type")
			self.__data__ = clipboard.wait_for_image()
		else:
			self.update()
			return
		#print self.__data__
		self.update()

	def __setattr__ (self, name, value):
		screenlets.Screenlet.__setattr__(self, name, value)
		if name == '_user_':
			self._user_ = value
		else if name == '_expire_duration_':
			if value == '0':
				self._expire_duration_ = 'd';
			else if value == '1':
				self._expire_duration_ = 'm';
			else:
				self._expire_duration_ = 'f';
		else if name == '_remember_me_':
			if value == True:
				self._remember_me_ = 1;
			else:
				self._remember_me_ = 0;
		else if name == 'service':
			self.service_name = value;
			self.service_url = self.__config__.get_url_by_service_name(value);
		else: pass

	def on_load_theme (self):
		"""Called when the theme is reloaded (after loading, before redraw)."""
		print ("Mouse on_mouse_up!")
		pass

	# custom functions
	def on_mouse_enter (self, event):
		print ("Mouse on_mouse_enter!")
		self.mouse_is_hover = True
		self.redraw_canvas()

	def on_mouse_leave (self, event):
		print ("Mouse on_mouse_leave!")
		self.mouse_is_hover = False
		self.mouse_press = False
		self.redraw_canvas()

	def on_mouse_down (self, event):
		print ("Mouse on_mouse_down!")
		if event.button == 1:
			if self.mouse_is_hover:
				self.mouse_press = True
		return False

	def on_mouse_up (self, event):
		self.show_notification("Mouse on_mouse_up!")
		# On left-click, open Dropbox folder
		if event.button == 1:
			#if self.mouse_is_hover:
				#os.system('xdg-open ' + self.db_path + ' &')
			self.mouse_press = False
		return False

	def draw_highlight (self, ctx, c):
		# draw highlight/flashing effect over a hovered item
		ctx.save()
		ctx.rectangle(0, 0, 50,	50)
		ctx.set_operator(cairo.OPERATOR_ATOP)
		ctx.set_source_rgba(c[0],c[1],c[2], c[3])
		ctx.fill()
		ctx.restore()
		ctx.set_operator(cairo.OPERATOR_OVER)

	def on_drag_enter (self, drag_context, x, y, timestamp):
		"""Called when something gets dragged into the Screenlets area."""
		print ("on_drag_enter!")
		self.dragging = True
		self.redraw_canvas()

	def on_drag_leave (self, drag_context, timestamp):
		"""Called when something gets dragged out of the Screenlets area."""
		print ("on_drag_leave!")
		self.dragging = False
		self.redraw_canvas()

	# drag and drop files or some sentences
	def on_drop (self, x, y, sel_data, timestamp):
		print ("on_drop!")
		content = ""
		contentType = "python"
		resp = ""

		# clipboard txt/img type
		if (self.__clipboard_type__ == True):
			content = self.__data__
		else:
			filename = ''
			filename = str(sel_data.get_text())
			filename = str.replace(filename,'%20','\ ')
			contentType = file_extension(filename);
			if filename.startswith('file://'):
				print ("Dropped: " + filename)
				filename = filename[7:len(filename)-1]
				# transfer to unicode
				filename = unicode(filename,"utf-8");
				filename = filename.encode("utf-8");
				# read file
				for line in fileinput.input(filename):
					content += line
				print "File content : " + content

		# combine param
		param =  "/pastebin.php parent_pid=";
		param += "&format=" + contentType;
		param += "&code2=" + content;
		param += "&poster=" + self._user_;
		param += "&paste=Send";
		param += "&remember=" + self._remember_me_;
		param += "&expiry=" + self._expire_duration_;
		param += "&email=";

		f_handler = urllib.urlopen(service_url, param);

		# handle connection failed, try default service
		# TODO: if failed, try other available services, one by one
		if f_handler == None:
			self.config_open_fault_handler();
			f_handler = urllib.urlopen(service_url, param);

		# handle the response
		for resp_line in f_handler.readlines():
			resp += resp_line;
		parser = HTMLResponseParser();
		parser.feed(resp);
		# paste to clipboard
		pasted_url_text = service_url + '/' + parser.pastebin_magic();
		print pasted_url_text;
		self.clipboard.set_text(pasted_url_text);
		self.clipboard.store();

	from os import os.path;
	# TODO: symblic link not supported!
	def file_extension(self, filename):
		"""Distinct file extension"""
		file_ext_switcher = {
			"txt" : lambda : "text",
			"py"  : lambda : "python",
			"php" : lambda : "php",
			"sh"  : lambda : "bash",
			"c"   : lambda : "c",
			"cpp" : lambda : "cpp",
			"h"   : lambda : "c",
			"hpp" : lambda : "cpp",
			"html": lambda : "html4strict",
			"htm" : lambda : "html4strict",
			"java": lambda : "java",
			"js"  : lambda : "javascript",
			"lua" : lambda : "lua",
			"ruby": lambda : "ruby", # FIXME
			"pl"  : lambda : "perl",
			"abap": lambda : "abap",
			"as"  : lambda : "actionscript",
			"ada" : lambda : "ada",
			"log" : lambda : "apache", # FIXME
			"applescript":lambda : "applescript", # FIXME
			"asm" : lambda : "asm",
			"asp" : lambda : "asp",
			"autoit":lambda: "autoit",
			"cs"  : lambda : "csharp",
			"css" : lambda : "css",
			"d"   : lambda : "d",
			"f"   : lambda : "fortran",
			"xml" : lambda : "xml",
			"sql" : lambda : "sql"
		}[key]();
		# default staff
		# split the file extension from raw name
		ext = os.path.splitext(filename)[1];
		return file_ext_switcher.get(ext, lambda : "text")();

	def on_quit (self):
		"""Callback for handling destroy-event. Perform your cleanup here!"""
		return True

	def on_draw (self, ctx):
		# Set icons
		icon_path = self.get_screenlet_dir() + "/themes/" + self.theme_name
		logo_icon = icon_path + '/pastebin.png'
		ctx.scale(self.scale, self.scale)
		ctx.set_operator(cairo.OPERATOR_OVER)

		# Draw icons
		self.draw_scaled_image(ctx,0,0,logo_icon,50,50)
		# Give visual feedback of a mouse press
		if self.mouse_press:
			self.draw_highlight(ctx,(0,0,0,0.3))
		self.draw_scaled_image(ctx,25,25,logo_icon,25,25)

	def update (self):
		self.redraw_canvas()
		return True

	def on_draw_shape (self, ctx):
		self.on_draw(ctx)

if __name__ == "__main__":
	# create new session
	import screenlets.session
	screenlets.session.create_session(PastebinScreenlet)

